NexusPi Git Node
docs/mirror_releases.py 20ec0b4ee3f3e7a8b3c8d00dcdcd5afdcf2bc840 (20ec0b4e) Text, 5.74 KB
T8b949e#!/usr/bin/env python3
T8b949e"""Mirror RTNode GitHub release binaries into docs/firmware/<tag>/.
Why: GitHub's release-download URLs do not expose CORS headers, so the
browser-based web flasher (docs/index.html) cannot fetch them directly from
jrl290.github.io. By mirroring the .bin assets under GitHub Pages we get a
same-origin URL the browser is allowed to fetch.
Usage:
python3 docs/mirror_releases.py # mirror all known releases
python3 docs/mirror_releases.py --max 5 # only the most recent 5
python3 docs/mirror_releases.py --tag v1.0.28 # one specific tag
Outputs:
docs/firmware/<tag>/<asset>.bin # mirrored binaries
docs/firmware/versions.json # manifest consumed by index.html
Convention:
All published firmware releases are treated as Beta unless explicitly
promoted to a different stability level elsewhere.
"""
Tff7b72from T7ee787__future__ Tff7b72import Te6edf3annotations
Tff7b72import T7ee787argparse
Tff7b72import T7ee787json
Tff7b72import T7ee787os
Tff7b72import T7ee787sys
Tff7b72import T7ee787urllibT7ee787.T7ee787request
Tff7b72import T7ee787urllibT7ee787.T7ee787error
Tff7b72from T7ee787pathlib Tff7b72import Te6edf3Path
Te6edf3REPO Tff7b72= Ta5d6ff"Ta5d6ffjrl290/RTNode-HeltecV4Ta5d6ff"
Te6edf3API Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffhttps://api.github.com/repos/Tffd700{Te6edf3REPOTffd700}Ta5d6ff/releasesTa5d6ff"
Te6edf3ASSET_NAMES Tff7b72= Tb4b4b4(
Ta5d6ff"Ta5d6ffrtnode_heltec_v3.binTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffrtnode_heltec_v3_merged.binTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffrtnode_heltec_v4.binTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffrtnode_heltec_v4_merged.binTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3EXCLUDED_TAGS Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffv1.0.31Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffv1.0.32Ta5d6ff"Tb4b4b4,
Tb4b4b4}
Te6edf3DEFAULT_STABILITY Tff7b72= Ta5d6ff"Ta5d6ffbetaTa5d6ff"
Te6edf3DOCS_DIR Tff7b72= Te6edf3PathTb4b4b4(Tff7b72__file__Tb4b4b4)Tff7b72.Td2a8ffresolveTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffparent
Te6edf3FW_DIR Tff7b72= Te6edf3DOCS_DIR Tff7b72/ Ta5d6ff"Ta5d6fffirmwareTa5d6ff"
Te6edf3MANIFEST Tff7b72= Te6edf3FW_DIR Tff7b72/ Ta5d6ff"Ta5d6ffversions.jsonTa5d6ff"
Tff7b72def Td2a8ffload_manifestTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657listTb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3MANIFESTTff7b72.Td2a8ffexistsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4[Tb4b4b4]
Tff7b72tryTb4b4b4:
Te6edf3data Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3MANIFESTTff7b72.Td2a8ffread_textTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72except Tb4b4b4(Te6edf3jsonTff7b72.Td2a8ffJSONDecodeErrorTb4b4b4, Tf85149OSErrorTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4[Tb4b4b4]
Tff7b72return Tb4b4b4[Te6edf3entry Tff7b72for Te6edf3entry Tff7b72in Te6edf3data Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3entryTb4b4b4, Tffa657dictTb4b4b4) Tff7b72and Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftagTa5d6ff"Tb4b4b4)Tb4b4b4]
Tff7b72def Td2a8ffsort_manifestTb4b4b4(Te6edf3entriesTb4b4b4: Tffa657listTb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4) Tff7b72-Tff7b72> Tffa657listTb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4:
Tff7b72return Tffa657sortedTb4b4b4(
Te6edf3entriesTb4b4b4,
Te6edf3keyTff7b72=Tff7b72lambda Te6edf3entryTb4b4b4: Tb4b4b4(Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpublished_atTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4, Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftagTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3reverseTff7b72=Tff7b72TrueTb4b4b4,
Tb4b4b4)
Tff7b72def Td2a8ffmerge_manifestTb4b4b4(Te6edf3existingTb4b4b4: Tffa657listTb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4, Te6edf3updatesTb4b4b4: Tffa657listTb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4) Tff7b72-Tff7b72> Tffa657listTb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4:
Te6edf3by_tag Tff7b72= Tb4b4b4{Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6fftagTa5d6ff"Tb4b4b4]Tb4b4b4: Te6edf3entry Tff7b72for Te6edf3entry Tff7b72in Te6edf3existing Tff7b72if Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftagTa5d6ff"Tb4b4b4)Tb4b4b4}
Tff7b72for Te6edf3entry Tff7b72in Te6edf3updatesTb4b4b4:
Te6edf3by_tagTb4b4b4[Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6fftagTa5d6ff"Tb4b4b4]Tb4b4b4] Tff7b72= Te6edf3entry
Tff7b72return Te6edf3sort_manifestTb4b4b4(Tffa657listTb4b4b4(Te6edf3by_tagTff7b72.Td2a8ffvaluesTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8ffgh_getTb4b4b4(Te6edf3urlTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657bytesTb4b4b4:
Te6edf3req Tff7b72= Te6edf3urllibTff7b72.Td2a8ffrequestTff7b72.Td2a8ffRequestTb4b4b4(Te6edf3urlTb4b4b4, Te6edf3headersTff7b72=Tb4b4b4{
Ta5d6ff"Ta5d6ffAcceptTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffapplication/vnd.github+jsonTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffUser-AgentTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffrtnode-mirror-scriptTa5d6ff"Tb4b4b4,
Tb4b4b4}Tb4b4b4)
Te6edf3token Tff7b72= Te6edf3osTff7b72.Td2a8ffenvironTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffGITHUB_TOKENTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3tokenTb4b4b4:
Te6edf3reqTff7b72.Td2a8ffadd_headerTb4b4b4(Ta5d6ff"Ta5d6ffAuthorizationTa5d6ff"Tb4b4b4, Ta5d6fffTa5d6ff"Ta5d6ffBearer Tffd700{Te6edf3tokenTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72with Te6edf3urllibTff7b72.Td2a8ffrequestTff7b72.Td2a8ffurlopenTb4b4b4(Te6edf3reqTb4b4b4) Tff7b72as Te6edf3rTb4b4b4:
Tff7b72return Te6edf3rTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8fflist_releasesTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657listTb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4:
Te6edf3outTb4b4b4: Tffa657listTb4b4b4[Tffa657dictTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3page Tff7b72= T79c0ff1
Tff7b72while Tff7b72TrueTb4b4b4:
Te6edf3data Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3gh_getTb4b4b4(Ta5d6fffTa5d6ff"Tffd700{Te6edf3APITffd700}Ta5d6ff?per_page=100&page=Tffd700{Te6edf3pageTffd700}Ta5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3dataTb4b4b4:
Tff7b72break
Te6edf3outTff7b72.Td2a8ffextendTb4b4b4(Te6edf3dataTb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3dataTb4b4b4) Tff7b72< T79c0ff100Tb4b4b4:
Tff7b72break
Te6edf3page Tff7b72+Tff7b72= T79c0ff1
Tff7b72return Te6edf3out
Tff7b72def Td2a8ffdownloadTb4b4b4(Te6edf3urlTb4b4b4: Tffa657strTb4b4b4, Te6edf3destTb4b4b4: Te6edf3PathTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3destTff7b72.Td2a8ffparentTff7b72.Td2a8ffmkdirTb4b4b4(Te6edf3parentsTff7b72=Tff7b72TrueTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3tmp Tff7b72= Te6edf3destTff7b72.Td2a8ffwith_suffixTb4b4b4(Te6edf3destTff7b72.Td2a8ffsuffix Tff7b72+ Ta5d6ff"Ta5d6ff.partTa5d6ff"Tb4b4b4)
Te6edf3req Tff7b72= Te6edf3urllibTff7b72.Td2a8ffrequestTff7b72.Td2a8ffRequestTb4b4b4(Te6edf3urlTb4b4b4, Te6edf3headersTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffUser-AgentTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffrtnode-mirror-scriptTa5d6ff"Tb4b4b4}Tb4b4b4)
Tff7b72with Te6edf3urllibTff7b72.Td2a8ffrequestTff7b72.Td2a8ffurlopenTb4b4b4(Te6edf3reqTb4b4b4) Tff7b72as Te6edf3rTb4b4b4, Tffa657openTb4b4b4(Te6edf3tmpTb4b4b4, Ta5d6ff"Ta5d6ffwbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Tff7b72while Tff7b72TrueTb4b4b4:
Te6edf3chunk Tff7b72= Te6edf3rTff7b72.Td2a8ffreadTb4b4b4(T79c0ff64 Tff7b72* T79c0ff1024Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3chunkTb4b4b4:
Tff7b72break
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3chunkTb4b4b4)
Te6edf3tmpTff7b72.Td2a8ffreplaceTb4b4b4(Te6edf3destTb4b4b4)
Tff7b72def Td2a8ffmirrorTb4b4b4(Te6edf3releasesTb4b4b4: Tffa657listTb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4) Tff7b72-Tff7b72> Tffa657listTb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4:
Te6edf3manifestTb4b4b4: Tffa657listTb4b4b4[Tffa657dictTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3rel Tff7b72in Te6edf3releasesTb4b4b4:
Te6edf3tag Tff7b72= Te6edf3relTb4b4b4[Ta5d6ff"Ta5d6fftag_nameTa5d6ff"Tb4b4b4]
Tff7b72if Te6edf3tag Tff7b72in Te6edf3EXCLUDED_TAGSTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff - Tffd700{Te6edf3tagTffd700}Ta5d6ff: excluded, skippingTa5d6ff"Tb4b4b4)
Tff7b72continue
Te6edf3assets Tff7b72= Tb4b4b4{Te6edf3aTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]Tb4b4b4: Te6edf3a Tff7b72for Te6edf3a Tff7b72in Te6edf3relTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffassetsTa5d6ff"Tb4b4b4, Tb4b4b4[Tb4b4b4]Tb4b4b4)Tb4b4b4}
Te6edf3present Tff7b72= Tb4b4b4[Te6edf3n Tff7b72for Te6edf3n Tff7b72in Te6edf3ASSET_NAMES Tff7b72if Te6edf3n Tff7b72in Te6edf3assetsTb4b4b4]
Tff7b72if Tff7b72not Te6edf3presentTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff - Tffd700{Te6edf3tagTffd700}Ta5d6ff: no recognised .bin assets, skippingTa5d6ff"Tb4b4b4)
Tff7b72continue
Te6edf3tag_dir Tff7b72= Te6edf3FW_DIR Tff7b72/ Te6edf3tag
Tff7b72for Te6edf3name Tff7b72in Te6edf3presentTb4b4b4:
Te6edf3dest Tff7b72= Te6edf3tag_dir Tff7b72/ Te6edf3name
Tff7b72if Te6edf3destTff7b72.Td2a8ffexistsTb4b4b4(Tb4b4b4) Tff7b72and Te6edf3destTff7b72.Td2a8ffstatTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffst_size Tff7b72== Te6edf3assetsTb4b4b4[Te6edf3nameTb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffsizeTa5d6ff"Tb4b4b4]Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff = Tffd700{Te6edf3tagTffd700}Ta5d6ff/Tffd700{Te6edf3nameTffd700}Ta5d6ff (Tffd700{Te6edf3destTff7b72.Td2a8ffstatTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffst_sizeTffd700}Ta5d6ff bytes, cached)Ta5d6ff"Tb4b4b4)
Tff7b72continue
Te6edf3url Tff7b72= Te6edf3assetsTb4b4b4[Te6edf3nameTb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffbrowser_download_urlTa5d6ff"Tb4b4b4]
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff + Tffd700{Te6edf3tagTffd700}Ta5d6ff/Tffd700{Te6edf3nameTffd700}Ta5d6ff <- Tffd700{Te6edf3urlTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3downloadTb4b4b4(Te6edf3urlTb4b4b4, Te6edf3destTb4b4b4)
Tff7b72except Te6edf3urllibTff7b72.Td2a8fferrorTff7b72.Td2a8ffHTTPError Tff7b72as Te6edf3eTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff ! HTTP Tffd700{Te6edf3eTff7b72.Td2a8ffcodeTffd700}Ta5d6ff fetching Tffd700{Te6edf3urlTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72continue
Te6edf3manifestTff7b72.Td2a8ffappendTb4b4b4(Tb4b4b4{
Ta5d6ff"Ta5d6fftagTa5d6ff"Tb4b4b4: Te6edf3tagTb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3relTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3tagTb4b4b4,
Ta5d6ff"Ta5d6ffstabilityTa5d6ff"Tb4b4b4: Te6edf3DEFAULT_STABILITYTb4b4b4,
Ta5d6ff"Ta5d6ffprereleaseTa5d6ff"Tb4b4b4: Te6edf3relTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffprereleaseTa5d6ff"Tb4b4b4, Tff7b72FalseTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffpublished_atTa5d6ff"Tb4b4b4: Te6edf3relTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpublished_atTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffassetsTa5d6ff"Tb4b4b4: Tffa657sortedTb4b4b4(Te6edf3presentTb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4)
Tff7b72return Te6edf3manifest
Tff7b72def Td2a8ffmainTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657intTb4b4b4:
Te6edf3p Tff7b72= Te6edf3argparseTff7b72.Td2a8ffArgumentParserTb4b4b4(Te6edf3descriptionTff7b72=Tff7b72__doc__Tb4b4b4)
Te6edf3pTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--maxTa5d6ff"Tb4b4b4, Tffa657typeTff7b72=Tffa657intTb4b4b4, Te6edf3defaultTff7b72=T79c0ff0Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffonly mirror the N most recent releases (0 = all)Ta5d6ff"Tb4b4b4)
Te6edf3pTff7b72.Td2a8ffadd_argumentTb4b4b4(Ta5d6ff"Ta5d6ff--tagTa5d6ff"Tb4b4b4, Te6edf3actionTff7b72=Ta5d6ff"Ta5d6ffappendTa5d6ff"Tb4b4b4, Te6edf3defaultTff7b72=Tb4b4b4[Tb4b4b4]Tb4b4b4, Te6edf3helpTff7b72=Ta5d6ff"Ta5d6ffmirror only this tag (may be repeated)Ta5d6ff"Tb4b4b4)
Te6edf3args Tff7b72= Te6edf3pTff7b72.Td2a8ffparse_argsTb4b4b4(Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFetching release list for Tffd700{Te6edf3REPOTffd700}Ta5d6ff...Ta5d6ff"Tb4b4b4)
Te6edf3releases Tff7b72= Te6edf3list_releasesTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3argsTff7b72.Td2a8fftagTb4b4b4:
Te6edf3releases Tff7b72= Tb4b4b4[Te6edf3r Tff7b72for Te6edf3r Tff7b72in Te6edf3releases Tff7b72if Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6fftag_nameTa5d6ff"Tb4b4b4] Tff7b72in Te6edf3argsTff7b72.Td2a8fftagTb4b4b4]
Tff7b72if Te6edf3argsTff7b72.Td2a8ffmax Tff7b72> T79c0ff0Tb4b4b4:
Te6edf3releases Tff7b72= Te6edf3releasesTb4b4b4[Tb4b4b4: Te6edf3argsTff7b72.Td2a8ffmaxTb4b4b4]
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffMirroring Tffd700{Tffa657lenTb4b4b4(Te6edf3releasesTb4b4b4)Tffd700}Ta5d6ff release(s) into Tffd700{Te6edf3FW_DIRTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3manifest Tff7b72= Te6edf3mirrorTb4b4b4(Te6edf3releasesTb4b4b4)
Tff7b72if Te6edf3argsTff7b72.Td2a8fftagTb4b4b4:
Te6edf3manifest Tff7b72= Te6edf3merge_manifestTb4b4b4(Te6edf3load_manifestTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3manifestTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3manifest Tff7b72= Te6edf3sort_manifestTb4b4b4(Te6edf3manifestTb4b4b4)
Te6edf3MANIFESTTff7b72.Td2a8ffparentTff7b72.Td2a8ffmkdirTb4b4b4(Te6edf3parentsTff7b72=Tff7b72TrueTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3MANIFESTTff7b72.Td2a8ffwrite_textTb4b4b4(Te6edf3jsonTff7b72.Td2a8ffdumpsTb4b4b4(Te6edf3manifestTb4b4b4, Te6edf3indentTff7b72=T79c0ff2Tb4b4b4) Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffWrote Tffd700{Te6edf3MANIFESTTffd700}Ta5d6ff (Tffd700{Tffa657lenTb4b4b4(Te6edf3manifestTb4b4b4)Tffd700}Ta5d6ff versions)Ta5d6ff"Tb4b4b4)
Tff7b72return T79c0ff0
Tff7b72if Tff7b72__name__ Tff7b72== Ta5d6ff"Ta5d6ff__main__Ta5d6ff"Tb4b4b4:
Te6edf3sysTff7b72.Td2a8ffexitTb4b4b4(Te6edf3mainTb4b4b4(Tb4b4b4)Tb4b4b4)
Served by rngit 1.4.2 - Generated in 0.03s